package top.ieei.demo.ftp.server;

import java.util.ArrayList;
import java.util.List;

import org.apache.ftpserver.ConnectionConfigFactory;
import org.apache.ftpserver.FtpServerFactory;
import org.apache.ftpserver.ftplet.Authority;
import org.apache.ftpserver.ftplet.FtpException;
import org.apache.ftpserver.ftplet.UserManager;
import org.apache.ftpserver.impl.DefaultFtpServer;
import org.apache.ftpserver.listener.ListenerFactory;
import org.apache.ftpserver.usermanager.PropertiesUserManagerFactory;
import org.apache.ftpserver.usermanager.UserFactory;
import org.apache.ftpserver.usermanager.impl.ConcurrentLoginPermission;
import org.apache.ftpserver.usermanager.impl.TransferRatePermission;
import org.apache.ftpserver.usermanager.impl.WritePermission;

public final class FtpServer implements IFtpService
{
	/** 匿名用户的最大数量 */
	private static final int MAX_ANONYMOUS_COUNT;

	private static final int PORT;

	private static FtpServer service = new FtpServer();

	/** FTP服务器 */
	private DefaultFtpServer server;

	/** 用户管理器 */
	private UserManager userMng;

	private FtpServerAuth auth;

	static
	{
		PORT = Integer.valueOf(StaticObj.getProperties().getProperty(
				"ftp.port", "21"));
		MAX_ANONYMOUS_COUNT = Integer.valueOf(StaticObj.getProperties()
				.getProperty("ftp.max_anonymous_count", "5"));
	}

	private FtpServer()
	{

	}

	public static FtpServer getInstance()
	{
		return service;
	}

	/**
	 * @return
	 */
	@Override
	public synchronized boolean isStoped()
	{
		return server.isStopped();
	}

	/**
	 * 
	 * 初始化ftp服务
	 * 
	 * @return void
	 * @exception throws
	 * @see
	 */
	private void initServer()
	{
		FtpServerFactory serverFactory = new FtpServerFactory();

		// 添加监听器
		ListenerFactory factory = new ListenerFactory();
		factory.setPort(PORT);
		serverFactory.addListener("default", factory.createListener());

		// 添加用户管理器
		PropertiesUserManagerFactory userManagerFactory = new PropertiesUserManagerFactory();
		userMng = userManagerFactory.createUserManager();
		serverFactory.setUserManager(userMng);

		// 添加连接配置
		ConnectionConfigFactory connConfigFactory = new ConnectionConfigFactory();

		serverFactory.setConnectionConfig(connConfigFactory
				.createConnectionConfig());

		server = (DefaultFtpServer) serverFactory.createServer();

		if (auth.getEnableAnonymous())
		{
			connConfigFactory.setAnonymousLoginEnabled(true);
			connConfigFactory.setMaxAnonymousLogins(MAX_ANONYMOUS_COUNT);

			FtpEntry ftpEntry = new FtpEntry("D:/temp", true);
			this.enableAnonymous(ftpEntry);
		}
		else
		{
			FtpEntry ftpEntry = new FtpEntry("D:/temp", true);
			UserEntry userEntry = new UserEntry(auth.getUserName(),
					auth.getPassword(), ftpEntry);
			this.addUserEntry(userEntry);
		}
	}

	/**
	 * 启用匿名用户
	 * 
	 * @param FtpEntry
	 *            FTP服务目录
	 * @see
	 */
	private void enableAnonymous(FtpEntry entry)
	{
		UserEntry user = new UserEntry(UserEntry.USER_NAME_ANONYMOUS, "", entry);
		this.addUserEntry(user);
	}

	/**
	 * 添加用户条目
	 * 
	 * @param user
	 *            用户条目
	 * @see
	 */
	private synchronized void addUserEntry(UserEntry user)
	{
		UserFactory userFactory = new UserFactory();

		// 设置用户属性
		userFactory.setName(user.getUserName());
		userFactory.setPassword(user.getPassword());
		userFactory.setEnabled(true);

		// 设置服务目录属性
		FtpEntry entry = user.getEntry();
		userFactory.setHomeDirectory(entry.getHomeDir());

		List<Authority> auths = new ArrayList<Authority>();

		// 设置可写允许
		if (entry.hasWritePerm())
		{
			auths.add(new WritePermission());
		}

		// 设置连接数目允许
		ConcurrentLoginPermission clp = new ConcurrentLoginPermission(
				entry.getMaxConcurrentLogins(),
				entry.getMaxConcurrentLoginsPerIP());
		auths.add(clp);

		// 设置传输速率允许
		TransferRatePermission trp = new TransferRatePermission(
				entry.getMaxDownloadRate(), entry.getMaxUploadRate());
		auths.add(trp);

		userFactory.setAuthorities(auths);

		// 创建并添加用户 条目
		try
		{
			userMng.save(userFactory.createUser());
		}
		catch (FtpException e)
		{
			e.printStackTrace();
		}
	}

	/**
     * 
     */
	@Override
	public synchronized void startService(FtpServerAuth fsAuth)
	{
		try
		{
			if (null == server || server.isStopped())
			{
				this.auth = fsAuth;
				initServer();
				server.start();
			}

		}
		catch (Exception e)
		{
			e.printStackTrace();
		}

	}

	/**
	 * @return
	 */
	@Override
	public synchronized void stopService()
	{
		if (null != server)
		{
			server.stop();
		}
	}
}
